#include "GLFont.h"
#include <vector>


GLFont::GLFont()
{
	m_FontInfo = NULL;
	for (int i = 0; i < UTFONT_PAGES_COUNT; i++)
        m_Textures[i] = NULL;
}


GLFont::~GLFont()
{
	for (int i = 0; i < UTFONT_PAGES_COUNT; i++)
	{
		if (m_Textures[i])
			delete m_Textures[i];
	}

    delete m_FontInfo;
}


GLFont* GLFont::createFromFile(const char *fontName)
{
    UTFont *info = new UTFont(fontName);
    GLFont* font = NULL;

    if (info->isLoaded)
    {
        font = new GLFont();
        font->m_FontInfo = info;
        font->m_FileName = fontName;
        String path = font->m_FileName.getSubString(0, font->m_FileName.findLast('/'));
        path += '/';
        //load textures
        for (int i = 0; i < UTFONT_PAGES_COUNT; i++)
        {
            if (i < info->common.pages)
            {
                String ss(path);
                ss += info->pages[i].file;
                font->m_Textures[i] = GLTexture::createFromFile(ss.c_str(), GLTEX_EDGE);
            }
            else
            {
                font->m_Textures[i] = 0;
            }
        }
        //generate characters
        for (int i = 0; i < UTFONT_CHARS_COUNT; i++)
        {
            float x1 = (float)info->chars[i].x / (float)info->common.scaleW;
            float y1 = (float)info->chars[i].y / (float)info->common.scaleH;
            float x2 = (float)(info->chars[i].x + info->chars[i].width) / (float)info->common.scaleW;
            float y2 = (float)(info->chars[i].y + info->chars[i].height) / (float)info->common.scaleH;
            font->m_CharSrcRects[i].set(x1, y1, x2, y2);
        }
        printf("NEW RESOURCE: Font '%s'\n", fontName);
    }
    else
    {
        delete info;
    }

    return font;
}


void GLFont::drawText(float x, float y, const String& str, const Color& c) const
{
	if (!m_FontInfo)
		return;

    glPushMatrix();
    glTranslatef(x, y, 0);

    glEnable(GL_TEXTURE_2D);

	glColor(c);

	float adv_sum = 0;

	for (int i = 0; i < str.getLength(); i++)
	{
		int c = (int)str.getChar(i);

		float x1 = m_CharSrcRects[c].AA.x;
		float y1 = m_CharSrcRects[c].AA.y;
		float x2 = m_CharSrcRects[c].BB.x;
		float y2 = m_CharSrcRects[c].BB.y;
		float w = m_FontInfo->chars[c].width;
		float h = m_FontInfo->chars[c].height;
		float xo = m_FontInfo->chars[c].xoffset;
		float yo = m_FontInfo->chars[c].yoffset; //+ (m_FontInfo->common.base - m_FontInfo->common.lineHeight);
		float adv = m_FontInfo->chars[c].xadvance;

		if (i < str.getLength() - 1)
			adv += m_FontInfo->chars[c].kernings[(int)str.getChar(i + 1)];

		glBindTexture(GL_TEXTURE_2D, m_Textures[m_FontInfo->chars[c].page]->getTextureId());

		glBegin(GL_QUADS);
		glTexCoord2f(x1, y2); 	glVertex2f(xo, h+yo);
		glTexCoord2f(x1, y1); 	glVertex2f(xo, yo);
		glTexCoord2f(x2, y1); glVertex2f(xo+w, yo);
		glTexCoord2f(x2, y2); 	glVertex2f(xo+w, yo+h);
		glEnd();

		glTranslatef(adv, 0, 0);
		adv_sum += adv;
		if (c == '\n')
		{
			glTranslatef(-adv_sum, m_FontInfo->common.lineHeight, 0);
			adv_sum = 0;
		}
	}

	glDisable(GL_TEXTURE_2D);

	glPopMatrix();

	glDisable(GL_TEXTURE_2D);
}


void GLFont::drawText(const rectf& pos, const String& str, int align_x, int align_y, const Color& color) const
{
	if (!m_FontInfo)
		return;

    glPushMatrix();
    glTranslatef(pos.AA.x, pos.AA.y, 0);

	glEnable(GL_TEXTURE_2D);

	glColor(color);

	std::vector<String> lines;
	std::vector<int> lines_w;

	lines.push_back(String(256));
	lines_w.push_back(0);

	for (int i = 0, ln = 0; i < str.getLength(); i++)
	{
		int c = (int)str.getChar(i);
		if (c == '\n')
		{
			lines.push_back(String(256));
			lines_w.push_back(0);
			ln++;
		}
		else
		{
			lines[ln] += c;
			lines_w[ln] += m_FontInfo->chars[c].xadvance;
			if (i < str.getLength() - 1 && str.getChar(i + 1) != '\n')
				lines_w[ln] += m_FontInfo->chars[c].kernings[(int)str.getChar(i + 1)];
		}
	}

	int text_h = lines.size() * m_FontInfo->common.lineHeight;

	if (align_y == FA_CENTER)
		glTranslatef(0, pos.getHeight() / 2.0f - text_h / 2.0f, 0);
	else if (align_y == FA_BOTTOM)
		glTranslatef(0, pos.getHeight() - text_h, 0);


	for (int ln = 0; ln < (int)lines.size(); ln++)
	{
		glPushMatrix();

		if (align_x == FA_CENTER)
			glTranslatef(pos.getWidth() / 2.0f - lines_w[ln] / 2.0f, 0, 0);
		else if (align_x == FA_RIGHT)
			glTranslatef(pos.getWidth() - lines_w[ln], 0, 0);

        float adv_sum = 0;

		for (int i = 0; i < lines[ln].getLength(); i++)
		{
			int c = (int)lines[ln].getChar(i);

			float x1 = m_CharSrcRects[c].AA.x;
			float y1 = m_CharSrcRects[c].AA.y;
			float x2 = m_CharSrcRects[c].BB.x;
			float y2 = m_CharSrcRects[c].BB.y;
			float w = m_FontInfo->chars[c].width;
			float h = m_FontInfo->chars[c].height;
			float xo = m_FontInfo->chars[c].xoffset;
			float yo = m_FontInfo->chars[c].yoffset; //+ (m_FontInfo->common.base - m_FontInfo->common.lineHeight);
			float adv = m_FontInfo->chars[c].xadvance;
			if (i < lines[ln].getLength() - 1)
				adv += m_FontInfo->chars[c].kernings[(int)lines[ln].getChar(i + 1)];

			glBindTexture(GL_TEXTURE_2D, m_Textures[m_FontInfo->chars[c].page]->getTextureId());

			glBegin(GL_QUADS);
			glTexCoord2f(x1, y2); 	glVertex2f(xo, h+yo);
			glTexCoord2f(x1, y1); 	glVertex2f(xo, yo);
			glTexCoord2f(x2, y1); 	glVertex2f(xo+w, yo);
			glTexCoord2f(x2, y2); 	glVertex2f(xo+w, yo+h);
			glEnd();

			glTranslatef(adv, 0, 0);
			adv_sum += adv;
		}

		glPopMatrix();

		glTranslatef(0, m_FontInfo->common.lineHeight, 0);
	}

	glDisable(GL_TEXTURE_2D);

	glPopMatrix();

	glDisable(GL_TEXTURE_2D);
}







